package cn.tqfeiyang.springplus.generator.config;

import cn.tqfeiyang.springplus.generator.jdbc.TableInfo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import cn.tqfeiyang.springplus.generator.name.NameConverter;
import cn.tqfeiyang.springplus.generator.type.DateType;
import cn.tqfeiyang.springplus.generator.util.RuntimeUtils;
import lombok.Data;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 生成器配置
 */
@Data
public class GeneratorConfig {

    /**
     * 名称转换器
     */
    private NameConverter nameConverter = new NameConverter(this);

    /**
     * 数据库连接地址
     */
    private String jdbcUrl = "";

    /**
     * 数据库连接用户
     */
    private String jdbcUsername = "";

    /**
     * 数据库连接密码
     */
    private String jdbcPassword = "";

    /**
     * 数据库连接属性
     */
    private final Map<String, String> connectionProperties = new HashMap<>();

    /**
     * 软件作者
     */
    private String author = "tqfeiyang";

    /**
     * 电子邮件
     */
    private String email = "1787585212@qq.com";

    /**
     * 微信
     */
    private String wechat = "18576228047";

    /**
     * 电话
     */
    private String phone = "18576228047";

    /**
     * 注释日期格式
     */
    private String commentDateFormat = "yyyy-MM-dd";

    /**
     * 时间类型对应策略
     */
    private DateType dateType = DateType.TIME_PACK;

    /**
     * 生成文件的输出目录【 windows:D://  linux or mac:/tmp 】
     */
    private String outputDir = System.getProperty("os.name").toLowerCase().contains("windows") ? "D://" : "/tmp";

    /**
     * 是否打开输出目录
     */
    private boolean autoOpen = true;

    /**
     * 父包
     */
    private String rootPackage = "com.example.testproject";

    /**
     * 模块名
     */
    private String moduleName = "";

    /**
     * Apifox 目录名
     */
    private String apifoxFolder = "";

    /**
     * 表名的第一个单词作为模块名
     * 例如 warehouse_location 模块名为 warehouse
     */
    private boolean firstWordAsModuleName = false;

    /**
     * 指定生成的主键的ID类型
     */
    private IdType entityIdType = IdType.ASSIGN_ID;

    /**
     * 乐观锁字段名
     */
    private String versionColumnName = "version";

    /**
     * 逻辑删除字段名
     */
    private String logicDeleteColumnName = "deleted";

    /**
     * 创建时间字段名
     */
    private String createTimeColumnName = "create_time";

    /**
     * 创建人员字段名
     */
    private String createUserColumnName = "create_user";

    /**
     * 修改时间字段名
     */
    private String updateTimeColumnName = "update_time";

    /**
     * 修改人员字段名
     */
    private String updateUserColumnName = "update_user";

    /**
     * 字段填充设置
     */
    private final Set<TableFill> tableFills = new HashSet<>();

    /**
     * 自定义基础的Entity类，公共字段
     */
    private final Set<String> superEntityColumns = new HashSet<>();

    /**
     * 自定义忽略字段
     */
    private final Set<String> ignoreColumns = new HashSet<>();

    /**
     * Boolean类型字段是否移除is前缀（默认 true）<br>
     * 比如 : 数据库字段名称 : 'is_xxx',类型为 : tinyint. 在映射实体的时候则会去掉is,在实体类中映射最终结果为 xxx
     */
    private boolean booleanColumnRemoveIsPrefix = true;

    /**
     * 实体名是否要去掉表名前面的模块（默认 true）
     */
    private boolean entityNameRemoveModulePrefix = true;

    /**
     * 领域名是否要去掉表名前面的模块（默认 true）
     */
    private boolean domainNameRemoveModulePrefix = true;

    /**
     * 包名是否要增加模块名称（默认 true）
     */
    private boolean packageNameWithModule = true;

    /**
     * 包名是否要增加表名称（默认 true）
     */
    private boolean packageNameWithTable = false;

    /**
     * 表名模式
     */
    private String tableNamePattern = null;

    /**
     * 需要包含的表名，允许正则表达式（与exclude二选一配置）
     */
    private final Set<String> includeTables = new HashSet<>();

    /**
     * 需要排除的表名，允许正则表达式
     */
    private final Set<String> excludeTables = new HashSet<>();

    /**
     * 过滤表前缀
     * example: addTablePrefix("t_")
     * result: t_simple -> Simple
     */
    private final Set<String> tablePrefix = new HashSet<>();

    /**
     * 过滤表后缀
     * example: addTableSuffix("_0")
     * result: t_simple_0 -> Simple
     */
    private final Set<String> tableSuffix = new HashSet<>();

    /**
     * 过滤字段前缀
     * example: addFieldPrefix("is_")
     * result: is_deleted -> deleted
     */
    private final Set<String> fieldPrefix = new HashSet<>();

    /**
     * 过滤字段后缀
     * example: addFieldSuffix("_flag")
     * result: deleted_flag -> deleted
     */
    private final Set<String> fieldSuffix = new HashSet<>();

    /**
     * 是否跳过视图（默认 true）
     */
    private boolean skipView = true;

    public GeneratorConfig addIncludeTable(String... includeTable) {
        this.includeTables.addAll(Arrays.asList(includeTable));
        return this;
    }

    public GeneratorConfig addExcludeTable(String... excludeTable) {
        this.excludeTables.addAll(Arrays.asList(excludeTable));
        return this;
    }

    public GeneratorConfig addTablePrefix(String... tablePrefix) {
        this.tablePrefix.addAll(Arrays.asList(tablePrefix));
        return this;
    }

    public GeneratorConfig addTableSuffix(String... tableSuffix) {
        this.tableSuffix.addAll(Arrays.asList(tableSuffix));
        return this;
    }

    public GeneratorConfig addFieldPrefix(String... fieldPrefix) {
        this.fieldPrefix.addAll(Arrays.asList(fieldPrefix));
        return this;
    }

    public GeneratorConfig addFieldSuffix(String... fieldSuffix) {
        this.fieldSuffix.addAll(Arrays.asList(fieldSuffix));
        return this;
    }

    public GeneratorConfig addSuperEntityColumns(String... column) {
        this.superEntityColumns.addAll(Arrays.asList(column));
        return this;
    }

    public GeneratorConfig addIgnoreColumns(String... column) {
        this.ignoreColumns.addAll(Arrays.asList(column));
        return this;
    }

    public GeneratorConfig addTableFills(TableFill... fills) {
        this.tableFills.addAll(Arrays.asList(fills));
        return this;
    }

    /**
     * 打开输出目录
     */
    public void openOutputDir() {
        if (StringUtils.isBlank(outputDir) || !new File(outputDir).exists()) {
            System.err.println("未找到输出目录：" + outputDir);
        } else if (autoOpen) {
            try {
                RuntimeUtils.openDir(outputDir);
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    /**
     * 所有的数据表信息，保存到这里，后续处理关联时要用到
     */
    private List<TableInfo> allTables;

}
